<?php
/**
 * Created by Administrator
 * User: longli
 * Date: 2020/08/17
 * Time: 21:03
 * @link http://www.lmterp.cn
 */

namespace app\common\service\orders;


use app\common\library\OrderHelp;
use app\common\library\Tools;
use app\common\model\Account;
use app\common\model\AccountPlatform;
use app\common\model\Countries;
use app\common\model\Orders;
use app\common\model\OrdersDetail;
use app\common\model\ProductStore;
use app\common\model\ReportOrderDay;
use app\common\service\BaseService;
use app\common\service\product\PlatformService;
use app\common\service\product\ProductService;
use app\common\service\system\SystemService;
use think\Db;
use think\exception\DbException;
use think\facade\Log;
use think\Paginator;

/**
 * 订单服务类
 * Class OrderService
 * @package app\common\service\orders
 */
class OrderService extends BaseService
{
    /**
     * 添加订单
     * @param array $orderData 订单信息
     * @param bool $isSplit 是否为拆单，默认为不拆单
     * @date 2020/08/17
     * @author longli
     * @return Orders|bool
     * @example $orderData = [
     *     "order_no" => "订单号",
     *     "order_detail" => [  // 订单情况
     *          [
     *              "sku" => "sku",
     *              "account_id" => 1,
     *          ]
     *      ]
     * ]
     */
    public function addOrder($orderData = [], $isSplit = false)
    {
        $data = Orders::getFilterField($orderData);
        if(empty($data)) return false;
        $data = Tools::trim($data);
        try
        {
            Db::startTrans();
            $order = null;
            // 验证是否需要更新订单
            if(isset($data['order_id'])) $order = Orders::get($data['order_id']);
            if(empty($order) && !empty($data['order_sn'])) $order = Orders::get(['order_sn' => $data['order_sn']]);
            if(!$isSplit && empty($order) && !empty($data['account_id']) && !empty($data['order_no']))
                $order = Orders::get(["account_id" => $data['account_id'], "order_no" => $data['order_no']]);
            // 如果国家没有填入则自动带入国家名称
            if(empty($data['buyer_country']) && !empty($data['buyer_country_code']) && ($county = Countries::getByCode($data['buyer_country_code'])))
                $data['buyer_country'] = $county->name_ch;
            // 如果国家简码没有填则自动带入二给简码
            if(empty($data['buyer_country_code']) && !empty($data['buyer_country']) && ($county = Countries::getByName($data['buyer_country'])))
                $data['buyer_country_code'] = $county->code_two;
            // 如果没有填平台则自动带入
            if(empty($data['platform_name']) && !empty($data['account_id']) && ($account = Account::get($data['account_id'])))
                $data['platform_name'] = $account->platform->name;

            if(empty($order))
            {
                if(empty($data['total_price']))
                {
                    $data['total_price'] = 0;
                    foreach(['surcharge_price', 'shipping_price', 'order_price'] as $v)
                    {
                        if(!empty($data[$v]) && $data[$v] > 0) $data['total_price'] += $data[$v];
                    }
                }
                // 货币兑换
                if(empty($data['total_price_rmb']) && !empty($data['currency']) && !empty($data['total_price']))
                    $data['total_price_rmb'] = SystemService::getInstance()->exchangeRate($data['currency'], 'CNY', $data['total_price']);
                // 处理内部唯一订单号
                if(!isset($data['order_sn']))
                {
                    $platform = 'AUTO';
                    $site = '';
                    if(!empty($data['account_id']) && ($account = Account::get($data['account_id'])))
                    {
                        $platform = $account->platform->code;
                        $site = $account->platform->site;
                    }
                    $data['order_sn'] = OrderHelp::generatorOrderSn($platform, $site);
                }
                $order = Orders::create($data);
            }
            else
            {
                $order->save($data);
            }
            $this->addOrderDetail($order, $orderData['order_detail']);
            $order->total_qty = array_sum(array_column($order->detail->toArray(), 'qty')); // 计算订单总数
            $order->weight = ProductService::getInstance()->getTotalWeight($order); // 计算订单重量
            $order->save();
            Db::commit();
            return $order;
        }catch (DbException $exception)
        {
            Log::info(sprintf("添加订单有误，错误信息：%s", $exception->getMessage()));
            Db::rollback();
        }
        return false;
    }

    /**
     * 添加订单详情
     * @param Orders $order 订单
     * @param array $details 订单详情
     * @date 2020/08/18
     * @author longli
     * @return OrdersDetail|int|null
     */
    public function addOrderDetail(Orders $order, $details = [])
    {
        if(empty($details)) return null;
        if(isset($details[0]) && is_array($details[0]))
        {
            foreach($details as $detail)
            {
                $this->addOrderDetail($order, $detail);
            }
        }
        else
        {
            $data = OrdersDetail::getFilterField($details);
            if(empty($data)) return null;
            $data = Tools::trim($data);
            if(empty($data['sku'])) $data['sku'] = PlatformService::getInstance()->getSkuByPlatformSku($data['platform_sku']);
            if($productStore = ProductStore::getStoreBySku($data['sku']))
            {
                if(empty($data['store_id'])) $data['store_id'] = $productStore->store_id;
                if(empty($data['name_ch'])) $data['name_ch'] = $productStore->product->name_ch;
                if(empty($data['image'])) $data['image'] = !empty($productStore->image_url) ? $productStore->image_url : $productStore->product->image;
                if(empty($data['declare_en'])) $data['declare_en'] = $productStore->product->declare_en;
                if(empty($data['declare_ch'])) $data['declare_ch'] = $productStore->product->declare_ch;
                if(empty($data['declare_price'])) $data['declare_price'] = $productStore->product->declare_price; // 默认取产品库里的人民币申报价格
            }
            $data['order_id'] = $order->order_id;
            $data['order_no'] = $order->order_no;
            $where = !empty($data['detail_id'])
                ? ['detail_id' => $data['detail_id']]
                : ["order_id" => $order->order_id, "sku" => $data['sku']];
            return OrdersDetail::where($where)->count()
                ? OrdersDetail::get($where)->save($data)
                : OrdersDetail::create($data);
        }
    }

    /**
     * 搜索订单
     * @param array $search
     * @return Paginator
     * @date 2020/09/02
     * @author longli
     */
    public function search($search = [])
    {
        $detail = ['product_code', 'item_id', 'sku', 'platform_sku', 'name', 'name_ch', 'attr', 'qty', 'return_qty', 'price', 'is_bundle', 'declare_en', 'declare_ch', 'customer_remark'];
        $orders = Orders::getTableFields();
        $custom = ['label_url'];
        // 验证是否有子查询
        $dwhere = $where = [];
        foreach($search as $k => $v)
        {
            if(in_array($k, $custom)) continue;
            if(in_array($k, $orders))
            {
                $where[] = [$k, "in", $v];
            }
            else if(Tools::startWith($k, 'detail_') && in_array(substr($k, strlen('detail_')), $detail))
            {
                $dwhere[substr($k, strlen('detail_'))] = $v;
            }
        }
        if(isset($search['send_date'])) $where = array_merge($where, $this->parseScopeDateToWhere("sent_time", $search['send_date']));

        $ordersModel = Orders::where($where)->with(['detail', 'account', 'currcode']);

        if(!empty($search['start_date']))
        {
            $ordersModel->where($this->parseLayuiRangeDate('order_source_create_time', $search['start_date']));
        }

        if(isset($search['label_url']))
        {
            $ordersModel->where("label_url", $search['label_url']?"neq":"eq", "");
        }
        // 处理排序
        $sort = "order_id desc";
        if(!empty($search['sort']))
        {
            if($search['sort'] == 'latest_delivery_time')
            {
                $sort = "latest_delivery_time asc";
                $ordersModel->where("latest_delivery_time", ">=", date("Y-m-d"));
            }
            else
            {
                $sort = "{$search['sort']} desc";
            }
        }
        $ordersModel->order($sort);

        if(!empty($dwhere))
        {
            $ordersModel->where("order_id", "in", function($query)use($dwhere)
            {
                $query->table(OrdersDetail::getTable())->where($dwhere)->field("order_id");
            });
        }
        // 处理分页
        $limit = !empty($search['limit']) ? $search['limit'] : null;
        return $ordersModel->paginate($limit);
    }

    /**
     * 通过订单 id 删除订单
     * @param int|int[] $ids 订单ID
     * @return bool
     * @date 2020/09/02
     * @author longli
     */
    public function deleteOrderById($ids = [])
    {
        if(empty($ids)) return false;
        if(is_array($ids)) $ids = join(',', $ids);
        try
        {
            Db::startTrans();
            Orders::destroy($ids);
            OrdersDetail::destroy(function($query)use($ids){$query->where("order_id", "in", $ids);});
            Db::commit();
            return true;
        }catch(DbException $e)
        {
            Log::info(sprintf("订单删除失败, 订单ID【%s】", $ids));
            Db::rollback();
        }
        return false;
    }

    /**
     * 获取待申报订单
     * @return array|\PDOStatement|string|\think\Collection
     * @date 2020/09/25
     * @author longli
     */
    public function getDeclareOrder()
    {
        return Orders::with(["detail"])->where([
            ["channel_id", ">", 0],
            ["label_url", "=", ""],
            ["order_status", "IN", [Orders::ORDER_WAIT]],
            ["is_print", "=", Orders::PRINT_N],
            ["send_status", "IN", [Orders::SEND_WAIT, Orders::SEND_UPDATE, Orders::SEND_PART, Orders::SEND_WAIT_TIMEOUT]],
        ])->select();
    }

    /**
     * 添加统计订单
     * @param array $data 统计信息
     * @return ReportOrderDay|false
     * @date 2020/09/27
     * @author longli
     */
    public function addStatOrder($data = [])
    {
        $rData = ReportOrderDay::getFilterField($data);
        if(empty($rData)) return false;
        $rData = Tools::trim($rData);
        $report = null;
        if(isset($rData['day_id'])) $report = ReportOrderDay::get($rData['day_id']);
        if(empty($report) && isset($rData['stat_date']) && isset($rData['account_id']))
            $report = ReportOrderDay::get(['stat_date' => $rData['stat_date'], 'account_id' => $rData['account_id']]);
        if(!empty($report))
        {
            $report->save($rData);
        }
        else
        {
            $report = ReportOrderDay::create($rData);
        }
        return $report;
    }
}